/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package main;

/**
 *
 * @author dalexandre
 */
public class Particle {

	private int id;
	

	private double fitness;
    private Centroid [] centroids;
    private Particle localBestPosition;
    private Velocity [] velocities;

    public Particle(int id, int k) {
        this.id = id;
        this.centroids = new Centroid[k];
        this.velocities = new Velocity[k];
    }

    public void calculateFitness() {

        double result = 0;
        int numEmptyCentroids = this.centroids.length;
       
        for (Centroid centroid : centroids) {

            double sum = 0;

            for (DataVector trainningData : centroid.getAssignedDataVectors()) {

                sum += Util.calculateEuclidianDistance(trainningData, centroid);
               
            }

            if (centroid.getAssignedDataVectors().size() > 0) {
                result += sum / centroid.getAssignedDataVectors().size();
            }
            if(centroid.getAssignedDataVectors().size()!= 0){
            	numEmptyCentroids--;
            }
        }
        
        result = result / (this.centroids.length-numEmptyCentroids);
        
        this.fitness = result;

    }

    public void updateLocalBestPosition() {

        if (this.localBestPosition != null) {

            if (this.fitness < this.localBestPosition.getFitness()) {
                this.localBestPosition = this.clone();
            }

        } else {
            this.localBestPosition = this.clone();
        }

    }

    public void updatePosition() {

        for (int i = 0; i < this.centroids.length; i++) {

            for (int j = 0; j < this.centroids[i].getPosition().length; j++) {

                this.centroids[i].getPosition()[j] += this.velocities[i].getVelocities()[j];
                   
            }

        }

    }

    public Centroid[] getCentroids() {
        return centroids;
    }

    public void setCentroids(Centroid[] centroids) {
        this.centroids = centroids;
    }

    public double getFitness() {
        return fitness;
    }

    public void setFitness(double fitness) {
        this.fitness = fitness;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Particle getLocalBestPosition() {
        return localBestPosition;
    }

    public void setLocalBestPosition(Particle localBestPosition) {
        this.localBestPosition = localBestPosition;
    }

    public Velocity[] getVelocities() {
        return velocities;
    }

    public void setVelocities(Velocity[] velocities) {
        this.velocities = velocities;
    }

    @Override
    public Particle clone() {

        Particle clone = new Particle(this.id, this.centroids.length);

        clone.fitness = this.fitness;

        for (int i = 0; i < this.centroids.length; i++) {
            clone.getCentroids()[i] = this.centroids[i].clone();
        }

        for (int i = 0; i < this.velocities.length; i++) {
            clone.getVelocities()[i] = this.velocities[i].clone();
        }

        return clone;
        
    }

    @Override
    public String toString() {
        StringBuilder result = new StringBuilder("");

        result.append("\nID: " + this.id);
        result.append("\nFITNESS: " + this.fitness);
        result.append("\nCENTROIDES: ");

        result.append("\nCENTROIDES: ");
        int i = 0;
        for (Centroid centroid : centroids) {
            result.append("\n    C" + (i++) + " = " + (centroid.getAssignedDataVectors().size()));
        }

        return result.toString();
    }

}
